import { ac } from '@coderline/alphatab-alphatex//metadata/bar/ac';
import { accidentals } from '@coderline/alphatab-alphatex//metadata/bar/accidentals';
import { ae } from '@coderline/alphatab-alphatex//metadata/bar/ae';
import { barlineLeft } from '@coderline/alphatab-alphatex//metadata/bar/barlineleft';
import { barlineRight } from '@coderline/alphatab-alphatex//metadata/bar/barlineright';
import { clef } from '@coderline/alphatab-alphatex//metadata/bar/clef';
import { ft } from '@coderline/alphatab-alphatex//metadata/bar/ft';
import { jump } from '@coderline/alphatab-alphatex//metadata/bar/jump';
import { ks } from '@coderline/alphatab-alphatex//metadata/bar/ks';
import { ottava } from '@coderline/alphatab-alphatex//metadata/bar/ottava';
import { rc } from '@coderline/alphatab-alphatex//metadata/bar/rc';
import { ro } from '@coderline/alphatab-alphatex//metadata/bar/ro';
import { scale } from '@coderline/alphatab-alphatex//metadata/bar/scale';
import { section } from '@coderline/alphatab-alphatex//metadata/bar/section';
import { simile } from '@coderline/alphatab-alphatex//metadata/bar/simile';
import { spd } from '@coderline/alphatab-alphatex//metadata/bar/spd';
import { sph } from '@coderline/alphatab-alphatex//metadata/bar/sph';
import { spu } from '@coderline/alphatab-alphatex//metadata/bar/spu';
import { sync } from '@coderline/alphatab-alphatex//metadata/bar/sync';
import { tempo } from '@coderline/alphatab-alphatex//metadata/bar/tempo';
import { tf } from '@coderline/alphatab-alphatex//metadata/bar/tf';
import { ts } from '@coderline/alphatab-alphatex//metadata/bar/ts';
import { width } from '@coderline/alphatab-alphatex//metadata/bar/width';
import { album } from '@coderline/alphatab-alphatex//metadata/score/album';
import { artist } from '@coderline/alphatab-alphatex//metadata/score/artist';
import { bracketExtendMode } from '@coderline/alphatab-alphatex//metadata/score/bracketextendmode';
import { copyright } from '@coderline/alphatab-alphatex//metadata/score/copyright';
import { copyright2 } from '@coderline/alphatab-alphatex//metadata/score/copyright2';
import { defaultSystemsLayout } from '@coderline/alphatab-alphatex//metadata/score/defaultsystemslayout';
import { firstSystemTrackNameMode } from '@coderline/alphatab-alphatex//metadata/score/firstsystemtracknamemode';
import { firstSystemTrackNameOrientation } from '@coderline/alphatab-alphatex//metadata/score/firstsystemtracknameorientation';
import { hideDynamics } from '@coderline/alphatab-alphatex//metadata/score/hidedynamics';
import { instructions } from '@coderline/alphatab-alphatex//metadata/score/instructions';
import { multiBarRest } from '@coderline/alphatab-alphatex//metadata/score/multibarrest';
import { multiTrackTrackNamePolicy } from '@coderline/alphatab-alphatex//metadata/score/multitracktracknamepolicy';
import { music } from '@coderline/alphatab-alphatex//metadata/score/music';
import { notices } from '@coderline/alphatab-alphatex//metadata/score/notices';
import { otherSystemsTrackNameMode } from '@coderline/alphatab-alphatex//metadata/score/othersystemtracknamemode';
import { otherSystemsTrackNameOrientation } from '@coderline/alphatab-alphatex//metadata/score/othersystemtracknameorientation';
import { showDynamics } from '@coderline/alphatab-alphatex//metadata/score/showdynamics';
import { singleTrackTrackNamePolicy } from '@coderline/alphatab-alphatex//metadata/score/singletracktracknamepolicy';
import { subtitle } from '@coderline/alphatab-alphatex//metadata/score/subtitle';
import { systemsLayout } from '@coderline/alphatab-alphatex//metadata/score/systemslayout';
import { tab } from '@coderline/alphatab-alphatex//metadata/score/tab';
import { title } from '@coderline/alphatab-alphatex//metadata/score/title';
import { useSystemSignSeparator } from '@coderline/alphatab-alphatex//metadata/score/usesystemsignseparator';
import { words } from '@coderline/alphatab-alphatex//metadata/score/words';
import { wordsAndMusic } from '@coderline/alphatab-alphatex//metadata/score/wordsandmusic';
import { articulation } from '@coderline/alphatab-alphatex//metadata/staff/articulation';
import { capo } from '@coderline/alphatab-alphatex//metadata/staff/capo';
import { chord } from '@coderline/alphatab-alphatex//metadata/staff/chord';
import { displayTranspose } from '@coderline/alphatab-alphatex//metadata/staff/displaytranspose';
import { lyrics } from '@coderline/alphatab-alphatex//metadata/staff/lyrics';
import { transpose } from '@coderline/alphatab-alphatex//metadata/staff/transpose';
import { tuning } from '@coderline/alphatab-alphatex//metadata/staff/tuning';
import { staff } from '@coderline/alphatab-alphatex//metadata/structural/staff';
import { track } from '@coderline/alphatab-alphatex//metadata/structural/track';
import { voice } from '@coderline/alphatab-alphatex//metadata/structural/voice';
import { ad } from '@coderline/alphatab-alphatex//properties/beat/ad';
import { au } from '@coderline/alphatab-alphatex//properties/beat/au';
import { balance } from '@coderline/alphatab-alphatex//properties/beat/balance';
import { bank } from '@coderline/alphatab-alphatex//properties/beat/bank';
import { barre } from '@coderline/alphatab-alphatex//properties/beat/barre';
import { bd } from '@coderline/alphatab-alphatex//properties/beat/bd';
import { beam } from '@coderline/alphatab-alphatex//properties/beat/beam';
import { bu } from '@coderline/alphatab-alphatex//properties/beat/bu';
import { ch } from '@coderline/alphatab-alphatex//properties/beat/ch';
import { cre } from '@coderline/alphatab-alphatex//properties/beat/cre';
import { d } from '@coderline/alphatab-alphatex//properties/beat/d';
import { dd } from '@coderline/alphatab-alphatex//properties/beat/dd';
import { dec } from '@coderline/alphatab-alphatex//properties/beat/dec';
import { ds } from '@coderline/alphatab-alphatex//properties/beat/ds';
import { dy } from '@coderline/alphatab-alphatex//properties/beat/dy';
import { f } from '@coderline/alphatab-alphatex//properties/beat/f';
import { fermata } from '@coderline/alphatab-alphatex//properties/beat/fermata';
import { fo } from '@coderline/alphatab-alphatex//properties/beat/fo';
import { glpf } from '@coderline/alphatab-alphatex//properties/beat/glpf';
import { glpt } from '@coderline/alphatab-alphatex//properties/beat/glpt';
import { gr } from '@coderline/alphatab-alphatex//properties/beat/gr';
import { instrument } from '@coderline/alphatab-alphatex//properties/beat/instrument';
import { legatoOrigin } from '@coderline/alphatab-alphatex//properties/beat/legatoOrigin';
import { beatLyrics } from '@coderline/alphatab-alphatex//properties/beat/lyrics';
import { ot } from '@coderline/alphatab-alphatex//properties/beat/ot';
import { p } from '@coderline/alphatab-alphatex//properties/beat/p';
import { rasg } from '@coderline/alphatab-alphatex//properties/beat/rasg';
import { s } from '@coderline/alphatab-alphatex//properties/beat/s';
import { sd } from '@coderline/alphatab-alphatex//properties/beat/sd';
import { slashed } from '@coderline/alphatab-alphatex//properties/beat/slashed';
import { beatSpd } from '@coderline/alphatab-alphatex//properties/beat/spd';
import { beatSpe } from '@coderline/alphatab-alphatex//properties/beat/spe';
import { beatSph } from '@coderline/alphatab-alphatex//properties/beat/sph';
import { beatSpu } from '@coderline/alphatab-alphatex//properties/beat/spu';
import { su } from '@coderline/alphatab-alphatex//properties/beat/su';
import { tb } from '@coderline/alphatab-alphatex//properties/beat/tb';
import { tbe } from '@coderline/alphatab-alphatex//properties/beat/tbe';
import { beatTempo } from '@coderline/alphatab-alphatex//properties/beat/tempo';
import { timer } from '@coderline/alphatab-alphatex//properties/beat/timer';
import { tp } from '@coderline/alphatab-alphatex//properties/beat/tp';
import { tt } from '@coderline/alphatab-alphatex//properties/beat/tt';
import { tu } from '@coderline/alphatab-alphatex//properties/beat/tu';
import { txt } from '@coderline/alphatab-alphatex//properties/beat/txt';
import { v } from '@coderline/alphatab-alphatex//properties/beat/v';
import { volume } from '@coderline/alphatab-alphatex//properties/beat/volume';
import { vs } from '@coderline/alphatab-alphatex//properties/beat/vs';
import { vw } from '@coderline/alphatab-alphatex//properties/beat/vw';
import { wahc } from '@coderline/alphatab-alphatex//properties/beat/wahc';
import { waho } from '@coderline/alphatab-alphatex//properties/beat/waho';
import { noteAccentuation } from '@coderline/alphatab-alphatex//properties/note/ac';
import { acc } from '@coderline/alphatab-alphatex//properties/note/acc';
import { ah } from '@coderline/alphatab-alphatex//properties/note/ah';
import { b } from '@coderline/alphatab-alphatex//properties/note/b';
import { be } from '@coderline/alphatab-alphatex//properties/note/be';
import { fh } from '@coderline/alphatab-alphatex//properties/note/fh';
import { g } from '@coderline/alphatab-alphatex//properties/note/g';
import { h } from '@coderline/alphatab-alphatex//properties/note/h';
import { hac } from '@coderline/alphatab-alphatex//properties/note/hac';
import { hide } from '@coderline/alphatab-alphatex//properties/note/hide';
import { iturn } from '@coderline/alphatab-alphatex//properties/note/iturn';
import { lf } from '@coderline/alphatab-alphatex//properties/note/lf';
import { lht } from '@coderline/alphatab-alphatex//properties/note/lht';
import { lmordent } from '@coderline/alphatab-alphatex//properties/note/lmordent';
import { lr } from '@coderline/alphatab-alphatex//properties/note/lr';
import { nh } from '@coderline/alphatab-alphatex//properties/note/nh';
import { ph } from '@coderline/alphatab-alphatex//properties/note/ph';
import { pm } from '@coderline/alphatab-alphatex//properties/note/pm';
import { psd } from '@coderline/alphatab-alphatex//properties/note/psd';
import { psu } from '@coderline/alphatab-alphatex//properties/note/psu';
import { rf } from '@coderline/alphatab-alphatex//properties/note/rf';
import { sh } from '@coderline/alphatab-alphatex//properties/note/sh';
import { sia } from '@coderline/alphatab-alphatex//properties/note/sia';
import { sib } from '@coderline/alphatab-alphatex//properties/note/sib';
import { sl } from '@coderline/alphatab-alphatex//properties/note/sl';
import { slur } from '@coderline/alphatab-alphatex//properties/note/slur';
import { sod } from '@coderline/alphatab-alphatex//properties/note/sod';
import { sou } from '@coderline/alphatab-alphatex//properties/note/sou';
import { ss } from '@coderline/alphatab-alphatex//properties/note/ss';
import { st } from '@coderline/alphatab-alphatex//properties/note/st';
import { string } from '@coderline/alphatab-alphatex//properties/note/string';
import { tiedNoteDash, t } from '@coderline/alphatab-alphatex//properties/note/t';
import { ten } from '@coderline/alphatab-alphatex//properties/note/ten';
import { th } from '@coderline/alphatab-alphatex//properties/note/th';
import { tr } from '@coderline/alphatab-alphatex//properties/note/tr';
import { turn } from '@coderline/alphatab-alphatex//properties/note/turn';
import { umordent } from '@coderline/alphatab-alphatex//properties/note/umordent';
import { noteVibrato } from '@coderline/alphatab-alphatex//properties/note/v';
import { noteVibratoWide } from '@coderline/alphatab-alphatex//properties/note/vw';
import { x } from '@coderline/alphatab-alphatex//properties/note/x';
import { metadata, properties } from '@coderline/alphatab-alphatex/common';
import { db } from '@coderline/alphatab-alphatex/metadata/bar/db';
import { extendBarLines } from '@coderline/alphatab-alphatex/metadata/score/extendbarlines';
import { instrumentMeta } from '@coderline/alphatab-alphatex/metadata/staff/instrument';
import type { AlphaTexExample, WithDescription, WithSignatures } from '@coderline/alphatab-alphatex/types';

export const structuralMetaData = metadata(track, staff, voice);
export const scoreMetaData = metadata(
    title,
    subtitle,
    artist,
    album,
    words,
    music,
    wordsAndMusic,
    copyright,
    copyright2,
    instructions,
    notices,
    tab,
    systemsLayout,
    defaultSystemsLayout,
    showDynamics,
    hideDynamics,
    useSystemSignSeparator,
    multiBarRest,
    bracketExtendMode,
    singleTrackTrackNamePolicy,
    multiTrackTrackNamePolicy,
    firstSystemTrackNameMode,
    otherSystemsTrackNameMode,
    firstSystemTrackNameOrientation,
    otherSystemsTrackNameOrientation,
    extendBarLines
);

export const staffMetaData = metadata(
    tuning,
    chord,
    capo,
    lyrics,
    articulation,
    displayTranspose,
    transpose,
    instrumentMeta
);

export const barMetaData = metadata(
    ts,
    ro,
    rc,
    ae,
    ks,
    clef,
    ottava,
    tempo,
    tf,
    ac,
    section,
    jump,
    ft,
    simile,
    barlineLeft,
    barlineRight,
    scale,
    width,
    sync,
    accidentals,
    spd,
    sph,
    spu,
    db
);

export const allMetadata = new Map([
    ...structuralMetaData.entries(),
    ...scoreMetaData.entries(),
    ...staffMetaData.entries(),
    ...barMetaData.entries()
]);

export const durationChangeProperties = properties(tu);

export const beatProperties = properties(
    f,
    fo,
    vs,
    v,
    vw,
    s,
    p,
    tt,
    d,
    dd,
    su,
    sd,
    cre,
    dec,
    beatSpd,
    beatSph,
    beatSpu,
    beatSpe,
    slashed,
    ds,
    glpf,
    glpt,
    waho,
    wahc,
    legatoOrigin,
    timer,
    tu,
    txt,
    beatLyrics,
    tb,
    tbe,
    bu,
    bd,
    au,
    ad,
    ch,
    gr,
    dy,
    beatTempo,
    volume,
    balance,
    tp,
    barre,
    rasg,
    ot,
    instrument,
    bank,
    fermata,
    beam
);

export const noteProperties = properties(
    nh,
    ah,
    th,
    ph,
    sh,
    fh,
    noteVibrato,
    noteVibratoWide,
    sl,
    ss,
    sib,
    sia,
    sou,
    sod,
    psu,
    psd,
    h,
    lht,
    g,
    noteAccentuation,
    hac,
    ten,
    tr,
    pm,
    st,
    lr,
    x,
    t,
    turn,
    iturn,
    umordent,
    lmordent,
    string,
    hide,
    b,
    be,
    lf,
    rf,
    acc,
    slur,
    tiedNoteDash
);

const spaces = /^([ ]+)/;

function trimIdention(txt: string) {
    const lines = txt.split('\n');
    const firstLineWithContent = lines.findIndex(l => l.trim() !== '');
    if (firstLineWithContent === -1) {
        return txt;
    }
    lines.splice(0, firstLineWithContent);

    const space = spaces.exec(lines[0]);
    if (space) {
        const trimmed = lines.map(l => l.substring(space[0].length));
        return trimmed.join('\n');
    }
    return lines.join('\n');
}

function prepareDescription(item: WithDescription) {
    const txt = item.longDescription;
    if (txt === undefined) {
        return;
    }

    const lines = txt.split('\n');
    if (lines[0].trim() === '') {
        lines.splice(0, 1);
    }

    const space = spaces.exec(lines[0]);
    if (space) {
        const trimmed = lines.map(l => l.substring(space[0].length));
        item.longDescription = trimmed.join('\n');
        if (!item.shortDescription) {
            item.shortDescription = trimmed[0].substring(0, 100);
        }
    } else if (!item.shortDescription) {
        item.shortDescription = lines[0].substring(0, 100);
    }
}

function prepareExample(d: AlphaTexExample) {
    if (typeof d === 'string') {
        return trimIdention(d);
    } else {
        d.tex = trimIdention(d.tex);
        return d;
    }
}
function prepareWithSignatures(d: WithSignatures) {
    prepareDescription(d);
    for (const s of d.signatures) {
        for (const p of s.parameters) {
            prepareDescription(p);
        }
    }

    if (Array.isArray(d.examples)) {
        for (const [i, e] of d.examples.entries()) {
            d.examples[i] = prepareExample(e);
        }
    } else {
        d.examples = prepareExample(d.examples);
    }
}

for (const d of allMetadata.values()) {
    prepareWithSignatures(d);
    if (d.properties) {
        for (const p of d.properties.values()) {
            prepareWithSignatures(p);
        }
    }
}

for (const d of beatProperties.values()) {
    prepareWithSignatures(d);
}

for (const d of noteProperties.values()) {
    prepareWithSignatures(d);
}
